#include "tyle.h"
#include "context.h"
#include <time.h>
#include "random.h"

void Tyle_init()
{
  //static int x=1/0;
  RNG.seed(time(0));
  Sess::session.init();
}

typedef Sess::ExternObject *Tyle_Object_t;

Tyle_Object          Tyle_evaluate(const char *program)
{
	return (Tyle_Object) Sess::session.evaluateToCopy((const unsigned char *)program);
} 

#define O_OBJ ((Object *)*(Tyle_Object_t)o)

Tyle_Object_Type     Tyle_getType( Tyle_Object o)
{
	return o ? (Tyle_Object_Type) O_OBJ->getTypeNum() : TOT_Null;
} 

int         Tyle_length(Tyle_Object o) { return O_OBJ->length(); }
Tyle_Object Tyle_index(Tyle_Object o, int index) 
{
  Sess::session.enterLite();
	Sess::ExternObject::MyList l;
	Object *space=l.prepend();
  O_OBJ->indexCopy(index,space);
	Tyle_Object r=(Tyle_Object)Sess::session.attachFirstExtern(l);
  Sess::session.leave();	
  return r; 
}
Tyle_Object Tyle_indexMap(Tyle_Object o, Tyle_Object index)
{ 
  Sess::session.enterLite();
	Sess::ExternObject::MyList l;
	Object *space=l.prepend();
  O_OBJ->indexCopy((Object *)index,space);
	Sess::session.m_externObjects.takeprependall(l);
	Tyle_Object r=(Tyle_Object)Sess::session.attachFirstExtern(l);
  Sess::session.leave();	
  return r;
}

int                  Tyle_toInt(Tyle_Object o)
{	return o ? O_OBJ->toInt() : 0;
} 
float                Tyle_toFloat(Tyle_Object o)
{	return o ? O_OBJ->toFloat() : 0;
} 

static char * Tyle_makeStringAnchor(String s, /*OUT*/ Tyle_Object &anchor, int *outLength)
{	
	Sess::ExternObject::MyList l;
	Object *space=l.prepend();
	new (space) StringObject(s);
	anchor =(Tyle_Object)Sess::session.attachFirstExtern(l);
	if (outLength) *outLength=s.length();
	return (char *) s;
} 

char *        Tyle_toString(Tyle_Object o, /*OUT*/ Tyle_Object *anchor, int *outLength)
{	
  Sess::session.enterLite();
	char *res=Tyle_makeStringAnchor(O_OBJ->toString(), *anchor, outLength);
  Sess::session.leave();	
  return res;
} 

char *        Tyle_toTyle(Tyle_Object o, /*OUT*/ Tyle_Object *anchor, int *outLength)
{	
	Sess::session.enterLite();
	char *res=Tyle_makeStringAnchor(O_OBJ->toTyle(), *anchor, outLength);
	Sess::session.leave();
	return res;
} 

void Tyle_free(Tyle_Object o)
{
	if (!o) return;
	Sess::session.enterLite();
	((Tyle_Object_t)o)->remove();
	Sess::session.leave();
}

void Tyle_stackString   (const char *str, int len)
{
	Sess::session.stackString(str,len);
}

void Tyle_block   ()
{
	Sess::session.m_evalCs.enter();
}

void Tyle_unblock   ()
{
	Sess::session.m_evalCs.leave();
}

void Tyle_quit   ()
{
	Sess::session.quit();
}
